package com.punch.system.util;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.punch.common.dto.system.dict.RedisDictDTO;
import com.punch.common.simple.redis.utils.RedisUtil;
import com.punch.common.utils.SpringUtil;
import com.punch.system.mapper.SysDictMapper;
import com.punch.system.model.SysDict;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * DictUtil-数据字典工具类
 *
 * @author wujj
 * @version 1.0.0
 * @since 2020/6/4 14:46
 */
public class DictUtil {

    private final static String DICT_KEY = "dict:";
    private static SysDictMapper dictMapper = SpringUtil.getBean(SysDictMapper.class);
    private static RedisUtil redisUtil = SpringUtil.getBean(RedisUtil.class);

    /**
     * 根据字典类型和值查询
     *
     * @param dictKey      字典key
     * @param value        字典值
     * @param defaultValue 默认值
     * @return label值
     */
    public static String getSysDictName(String dictKey, String value, String defaultValue) {
        RedisDictDTO redisDict = (RedisDictDTO) redisUtil.getHashObject(DICT_KEY + dictKey, value, RedisDictDTO.class);
        if (redisDict != null) {
            return redisDict.getName();
        } else {
            List<RedisDictDTO> dictList = getSysDictList(dictKey);
            List<RedisDictDTO> sysDictList = dictList.stream()
                    .filter(dict -> value.equals(dict.getValue())).collect(Collectors.toList());
            return sysDictList.size() < 1 ? defaultValue : sysDictList.get(0).getName();
        }
    }

    public static String getSysDictValue(String dictName, String dictKey, String defaultLabel) {
        if (StringUtils.isNotBlank(dictKey) && StringUtils.isNotBlank(dictName)) {
            for (RedisDictDTO dict : getSysDictList(dictKey)) {
                if (dictKey.equals(dict.getDictKey()) && dictName.equals(dict.getName())) {
                    return dict.getValue();
                }
            }
        }
        return defaultLabel;
    }

    /**
     * 多选时调用此方法获取多个值以逗号分隔
     *
     * @param dictKey 字典类型
     * @param values  逗号分隔的字典值
     * @return 逗号分隔的label值
     */
    public static String getSysDictNames(String dictKey, String values) {
        return Arrays.stream(values.split(","))
                .map(value -> getSysDictName(dictKey, value, ""))
                .collect(Collectors.joining(","));
    }

    public static String getSysDictFirstValue(String dictKey, String defaultValue) {
        List<RedisDictDTO> dictList = getSysDictList(dictKey);
        return dictList.size() < 1 ? defaultValue : dictList.get(0).getValue();

    }

    /**
     * 获取数据字典的单个数据信息
     *
     * @param dictKey
     * @return
     */
    public static RedisDictDTO getSysDictFirstDict(String dictKey) {
        List<RedisDictDTO> dictList = getSysDictList(dictKey);
        if (dictList != null && !dictList.isEmpty()) {
            return dictList.get(0);
        } else {
            return new RedisDictDTO();
        }
    }

    /**
     * 根据类型获取字典列表
     *
     * @param dictKey 字典类型
     * @return {@link List<RedisDictDTO>}
     */
    public static List<RedisDictDTO> getSysDictList(String dictKey) {
        Optional<List<RedisDictDTO>> redisDictList = Optional.ofNullable(redisUtil.getHashList(DICT_KEY + dictKey, RedisDictDTO.class));
        if (!redisDictList.isPresent() || redisDictList.get().size() < 1) {
            List<RedisDictDTO> dictList = putSysDict(dictKey);
            dictList.sort(Comparator.comparing(RedisDictDTO::getSortBy));
            return dictList;
        }
        redisDictList.get().sort(Comparator.comparing(RedisDictDTO::getSortBy));
        return redisDictList.orElse(null);
    }

    /**
     * 根据类型存储到redis中
     *
     * @param dictKey 字典类型
     * @return List<RedisDict> 现有的所有的字典
     */
    public static List<RedisDictDTO> putSysDict(String dictKey) {
        List<RedisDictDTO> dictList = dictMapper.selectRedisDictList(dictKey);
        redisUtil.putHashList(DICT_KEY + dictKey, DictUtil::apply, dictList);
        return dictList;
    }

    /**
     * 根据类型和名称模糊查询
     *
     * @param dictKey
     * @param dictName
     * @return
     */
    public static List<SysDict> getListByTypeAndName(String dictKey, String dictName) {
        List<SysDict> dictList = dictMapper.selectListBykeyOrName(dictKey, dictName);
        return dictList;
    }

    /**
     * 新增修改 字典
     *
     * @param redisDict
     */
    public static void putSysDict(RedisDictDTO redisDict) {
        redisUtil.putHashModel(DICT_KEY + redisDict.getDictKey(), DictUtil::apply, redisDict);
    }

    /**
     * 根据key删除(hash列表)字典
     *
     * @param redisDict {@link SysDict}
     */
    public static void delSysDictList(RedisDictDTO redisDict) {
        redisUtil.deleteValue(DICT_KEY + redisDict.getDictKey());
    }

    /**
     * 根据key删除(hash列表)字典
     *
     * @param dictKey {@link SysDict}
     */
    public static void delSysDictList(String dictKey) {
        redisUtil.deleteValue(DICT_KEY + dictKey);
    }


    /**
     * 根据key删除(hash)字典
     *
     * @param redisDict {@link SysDict}
     */
    public static void delSysDictModel(RedisDictDTO redisDict) {
        redisUtil.delHash(DICT_KEY + redisDict.getDictKey(), redisDict.getValue());
    }


    private static Object apply(Object t) {
        RedisDictDTO dict = (RedisDictDTO) t;
        return dict.getValue();
    }

    /**
     * 通过label和description进行取值
     *
     * @param dictName
     * @param dictKey
     * @param description
     * @return
     */
    public static String getDictValueByLabelAndDes(String dictName, String dictKey, String description) {
        if (StringUtils.isNotBlank(dictKey) && StringUtils.isNotBlank(dictName)) {
            for (RedisDictDTO dict : getSysDictList(dictKey)) {
                if (dictKey.equals(dict.getDictKey()) && dictName.equals(dict.getName())) {
                    return dict.getValue();
                }
            }
        }
        return "";
    }

    /**
     * 通过type类型集合获取所有字典实体
     *
     * @param dictKeys type类型集合
     * @return 字典实体集合
     * @author shijq
     * @since 2020-04-03
     */
    public static Collection<SysDict> getDictByTypeList(Collection<String> dictKeys) {
        return dictMapper.selectList(new LambdaQueryWrapper<SysDict>().in(SysDict::getDictKey, dictKeys));
    }
}
